import random

from flask import session

from info import redis_store, db
from info.libs.yuntongxun.sms import CCP
from info.models import User
from info.modules.passport import passport_blue
# from . import passport_blue
from info.response_code import RET
from info.utils.captcha.captcha import captcha
from flask import request, jsonify, make_response, current_app
from info import constants
import re


@passport_blue.route('/logout', methods=['POST'])
def logout():
    """
    功能:退出
    请求路径:/passport/logout
    请求方式:POST
    请求参数:无参数
    返回值:返回响应

    操作步骤:
    1.清除session
    2.返回响应
    :return:
    """
    # 1.清除session
    session.clear()
    # 2.返回响应
    return jsonify(errno=RET.OK, errmsg="退出成功")


@passport_blue.route('/login', methods=['POST'])
def login():
    """
    功能:登录
    请求路径:/passport/login
    请求方式:POST
    请求参数:mobile(手机号),password(密码)
    响应信息:errno(正确响应代码),errmsg("响应信息")

    操作步骤:
    1.获取参数mobile和密码
    2.参数为空校验
    3.手机号和密码与数据库中的校验
    4.返回响应
    :return:
    """
    # 1.获取参数mobile和密码
    json_dict = request.json
    mobile = json_dict.get("mobile")
    password = json_dict.get("password")

    # 2.参数为空校验
    if not all([mobile, password]):
        return jsonify(errno=RET.NODATA, errmsg="账号和密码不能为空")

    # 3.手机号和密码与数据库中的校验
    mysql_data = User.query.filter(User.mobile == mobile).first()
    print(mysql_data)
    if not mysql_data:
        return jsonify(errno=RET.DATAERR, errmsg="用户不存在")

    # 4.判断密码
    if mysql_data.password_hash != password:
        return jsonify(errno=RET.DATAERR, errmsg="密码错误")

    # 5.保存到session
    session["user_id"] = mysql_data.id
    session["nick_name"] = mysql_data.nick_name
    session["mobile"] = mysql_data.mobile


    # 6.返回响应
    return jsonify(errno=RET.OK, errmsg="登陆成功")


@passport_blue.route('/register', methods=['POST'])
def register():
    """
    功能:注册用户
    请求路径:/passport/register
    请求方式:POST
    请求参数:mobile(手机号),sms_code(短信验证码),password(密码)
    返回值:errno(错误代码),errmsg(错误信息描述)

    操作步骤:
    1.获取参数
    2.参数校验(为空,手机号格式)
    3.通过手机号取出redis中存储的短信验证码
    4.判断短信验证码是否过期
    5.删除redis中的短信验证码
    6.校验传入的短信验证码和redis中的是否相等
    7.创建用户对象,设置属性
    8.保存到数据库
    9.返回响应
    :return:
    """
    # 1.获取参数
    json_dict = request.json
    mobile = json_dict.get("mobile")
    sms_code = json_dict.get("sms_code")
    password = json_dict.get("password")

    # 2.参数校验(为空, 手机号格式)
    if not all([mobile, sms_code, password]):
        return jsonify(errno=RET.NODATA, errmsg="参数不能为空")

    if not re.match("1[35789]\d{9}", mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机号的格式错误")

    # 3.通过手机号取出redis中存储的短信验证码
    try:
        redis_sms_code = redis_store.get("sms_code:%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="获取验证码异常")

    # 4.判断短信验证码是否过期
    if not redis_sms_code:
        return jsonify(errno=RET.NODATA, errmsg="短信验证码已经过期了")

    # 5.删除redis中的短信验证码
    try:
        redis_store.delete("sms_code:%s" % mobile)
    except Exception as e:
        current_app.logger.error(e)
        return jsonify(errno=RET.DBERR, errmsg="redis删除失败")

    # 6.校验传入的短信验证码和redis中的是否相等
    if sms_code != redis_sms_code:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码填写错啦")

    # 7.创建用户对象, 设置属性
    user = User()
    user.nick_name = mobile
    user.password_hash = password
    user.mobile = mobile

    # 8.保存到数据库
    try:
        db.session.add(user)
        db.session.commit()
    except Exception as e:
        current_app.logger.error(e)
        db.session.rollback()
        return jsonify(errno=RET.DATAERR, errmsg="保存到数据库失败")

    # 9.返回响应
    return jsonify(errno=RET.OK, errmsg="注册成功!")


@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():
    """
    功能：发送短信验证码
    1.请求路径：/passport/sms_code
    2.请求方式：POST
    3.请求参数：手机号（tel_num）,随机生成的字符串（cur_id）,图片验证码（存储在redis中的）
    4.返回值：短信验证码jsonify

    操作步骤：
    1.获取参数（就是发送过来的3个）
    2.参数校验（一。根据传过来的cur_id来获取redis中存储的图片验证码的信息，校验图片验证码）
        （二。校验手机号 三.为空校验）
    3.查看图片验证码是否过期
    4.生成短信验证码，发送短信验证码ccp.send_template_sms('18209685653', ['6789', 5], 1)
    5.保存一份到redis中，然后让其不能点击
    6.返回响应
    :return:
    """
    # 1.获取参数
    json_dict = request.json
    mobile = json_dict.get("mobile")
    image_code = json_dict.get("image_code")
    image_code_id = json_dict.get("image_code_id")

    # 2.校验参数, 为空检验
    if not all([mobile, image_code, image_code_id]):
        return jsonify(errno=RET.PARAMERR, errmsg="参数不能为空")

    # 3.校验手机号格式
    if not re.match("1[3578]\d{9}", mobile):
        return jsonify(errno=RET.DATAERR, errmsg="手机号的格式有误!")

    # 4.根据传入的图片验证码编号获取redis中的图片验证码A
    redis_image_data_id = redis_store.get("image_data_id:%s" % image_code_id)

    # 5.判断图片验证码A, 是否过期
    if not redis_image_data_id:
        return jsonify(errno=RET.NODATA, errmsg="验证码已经过期了")

    # 6.删除redis中的图片验证码A
    redis_store.delete("image_data_id:%s" % image_code_id)

    # 7.判断传入的验证码B, 和redis中的验证码A是否相等
    if image_code != redis_image_data_id:
        return jsonify(errno=RET.DATAERR, errmsg="验证码输入错误!")

    # 8.生成短信验证码
    sms_code = "%06d" % random.randint(0, 999999)

    # 9.调用CCP发送, 并判断
    ccp = CCP()
    result = ccp.send_template_sms(mobile, [sms_code, constants.SMS_CODE_REDIS_EXPIRES/60], 1)

    if result == -1:
        return jsonify(errno=RET.DATAERR, errmsg="短信验证码发送失败")

    # 10.将短信验证码保存一份到redis
    redis_store.set("sms_code:%s" % mobile, sms_code, constants.SMS_CODE_REDIS_EXPIRES)

    # 11.返回响应
    return jsonify(errno=RET.OK, errmsg="短信验证码发送成功!")


# 功能: 获取图片验证码
@passport_blue.route('/image_code')
def image_code():
    """
    请求路径:/passport/image_code
    请求方式:GET
    请求参数:cur_id, pre_id
    返回值:返回图片信息
    1.首先得要获取参数
    2.参数校验,判断参数传递是否错误
    3.生成图片验证码
    4.判断是否有上一个图片的验证码的编号
    5.保存一份到redis中,若有,就删除前一个的,然后保存当前的
    6.返回图片验证码
    :return:图片验证码
    """
    # 1.获取参数
    cur_id = request.args.get("cur_id")
    pre_id = request.args.get("pre_id")
    # 2.参数校验
    if not cur_id:
        return "获取图片验证码的时候,需要携带随机字符串,您没有携带"

    # 3.生成图片验证码
    name, text, image_data = captcha.generate_captcha()
    print(text)

    try:
        # 4.判断是否有上一个图片验证码编号,若有,则删除
        if pre_id:
            redis_store.delete("image_data_id:%s" % pre_id)

        # 5.保存一份到redis中
        redis_store.set("image_data_id:%s" % cur_id, text, constants.IMAGE_CODE_REDIS_EXPIRES)
    except Exception as e:
        current_app.logger.error(e)
        return "redis操作图片失败"

    # 6.返回图片验证码(图片返回的类型要设置为image/jpg),要不然返回的东西就是二进制了
    response = make_response(image_data)
    response.headers["Content-Type"] = "image/jpg"
    return response